package nc.bs.gl.util;

import nc.bs.common.util.ArrayUtil;
import nc.bs.common.util.DaoUtil;
import nc.bs.common.util.GlDocFreeItem;
import nc.bs.common.util.GlFreeAssistUtil;
import nc.bs.common.util.ObjectUtils;
import nc.bs.common.util.SQLUtil;
import nc.bs.common.util.pojo.SettleRecord;
import nc.bs.common.util.pojo.TableMsg;
import nc.bs.common.util.pojo.TempAccountDetail;
import nc.jdbc.framework.processor.ColumnListProcessor;
import nc.vo.dbcache.query.LeftJoin;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author cloudwxjj
 * @date 2024/4/19-上午11:29
 */
public class GlDetailQueryBuilder {


    private GlDetailQueryCondition condition;
    private final SettleRecord record;

    private boolean empty;

    public GlDetailQueryBuilder(SettleRecord record) {
        this.record = record;
        init();
    }

    public GlDetailQueryBuilder(String accoungingBook,String yearmonth) {
        this.record = new SettleRecord(accoungingBook,yearmonth.substring(0,4),yearmonth.substring(5,6));
        init();
    }

    private void init() {
        condition = new GlDetailQueryCondition();
        condition.setAccountIngBook(record.getAccountingBook());
        condition.setYearMonth(record.getYear()+"-"+record.getMonth());
        this.empty = false;
    }

    public GlDetailQueryBuilder clear() {
        init();
        return this;
    }

    public GlDetailQueryBuilder select(String... selectColumns) {
        condition.setSelectColumn(selectColumns);
        return this;
    }

    public GlDetailQueryBuilder groupBy(String... groupByColumns) {
        condition.setGroupColumn(groupByColumns);
        return this;
    }

    public GlDetailQueryBuilder whereCondition(Map<String, String[]> whereCondition) {
        condition.setWhereColumn(whereCondition);
        return this;
    }

    private GlDetailQueryBuilder where(boolean not,String key, String[] values) {
        Map<String, String[]> whereColumn;
        if(not){
            whereColumn = condition.getWhereNotColumn();
        }else {
            whereColumn = condition.getWhereColumn();
        }
        if (whereColumn == null) {
            whereColumn = new HashMap<>();
            whereColumn.put(key, values);
        } else {
            String[] strings = whereColumn.get(key);
            if (strings == null) {
                whereColumn.put(key, values);
            } else {
                whereColumn.put(key, ArrayUtil.merge(strings, values));
            }
        }
        if(not){
            condition.setWhereNotColumn(whereColumn);
        }else {
            condition.setWhereColumn(whereColumn);
        }

        return this;
    }

    public GlDetailQueryBuilder leftJoin(String tableName,String aliasName,String joinCondition) {
        Set<String> leftJoin = condition.getLeftJoin();
        if(leftJoin == null){
            condition.setLeftJoin(new HashSet<>());
            leftJoin = condition.getLeftJoin();
        }
        leftJoin.add(" " + tableName + " " + aliasName + " on  " + joinCondition);
        return this;
    }


    public GlDetailQueryBuilder whereAccountCode(String... accountCodes){
        where(false,"substr("+GlDetailQueryUtil.VIEW_TABLE+"."+TempAccountDetail.citemcode+",0,"+accountCodes[0].length()+")" ,accountCodes);
        return this;
    }

    public GlDetailQueryBuilder whereAssiValue(String docCode,String... values) {
        return whereNotAssiValue(false,docCode,values);
    }


    public GlDetailQueryBuilder whereNotAssiValue(String docCode,String... values) {
        return whereNotAssiValue(true,docCode,values);
    }

    public GlDetailQueryBuilder delSy() {
        condition.setDelSy(true);
        return this;
    }

    private GlDetailQueryBuilder whereNotAssiValue(boolean not,String docCode,String... values) {
        GlDocFreeItem item = GlDocFreeItem.getItemByCode(docCode);
        Objects.requireNonNull(item);
        TableMsg tableMsg = GlFreeAssistUtil.queryFreeDocTableMsg(docCode);
        String sql = "select gl_docfree1.assid from gl_docfree1 left join " + tableMsg.getTableName() + " b on " +
                " gl_docfree1." + tableMsg.num + " = b." + tableMsg.pk + " where  1=1 " +
               " and gl_docfree1.assid in (SELECT ASSID FROM gl_detail WHERE YEARV||PERIODV between CONCAT(SUBSTR('"+record.getYear().concat(record.getMonth())+"', 0, 4), '00') and '"+record.getYear().concat(record.getMonth())+"'    " +
               "AND ASSID <> '~' ) " +
                "and ";
        if(not){
            sql = sql + SQLUtil.buildOrNotCondition("b."+item.getColumnCode(),values,true) ;
        }else {
            sql = sql + SQLUtil.buildOrNotCondition("b."+item.getColumnCode(),values,false) ;
        }
        List<String> assids = (List<String>) DaoUtil.executeQuery(sql, new ColumnListProcessor());
        if(ObjectUtils.isEmpty(assids)){
            //无符合条件的辅助项
            this.empty = true;
        }else {
            where(not,GlDetailQueryUtil.VIEW_TABLE+"."+TempAccountDetail.cassid,assids.toArray(new String[0]));
        }
        return this;
    }


    public GlDetailQueryBuilder extraSQL(String extraSQL) {
        condition.setExtraWhereSQL(extraSQL);
        return this;
    }

    public GlDetailQueryBuilder needAllAmount(){
        needInitData().needDebitData().needCreditData().needDebitSumData().needCreditSumData().needFinalData();
        return this;
    }

    public GlDetailQueryBuilder needInitNov() {
        condition.setNeedInitNov(true);
        return this;
    }

    public GlDetailQueryBuilder needInitData() {
        condition.setInitData(true);
        return this;
    }

    public GlDetailQueryBuilder needDebitData() {
        condition.setDebitData(true);
        return this;
    }

    public GlDetailQueryBuilder needCreditData() {
        condition.setCreditData(true);
        return this;
    }

    public GlDetailQueryBuilder needDebitSumData() {
        condition.setDebitSumData(true);
        return this;
    }

    public GlDetailQueryBuilder needCreditSumData() {
        condition.setCreditSumData(true);
        return this;
    }

    public GlDetailQueryBuilder needFinalData() {
        condition.setFinalData(true);
        return this;
    }

    public GlDetailQueryCondition getCondition() {
        return condition;
    }

    public List<TempAccountDetail> query() {
        if(empty){
            return null;
        }
        String sql = GlDetailQueryUtil.buildQuerySQL(getCondition());
        return DaoUtil.executeQueryList(sql, TempAccountDetail.class);
    }

}
